package org.example.common.configs.log;

import cn.hutool.core.collection.CollectionUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Aspect
@Component
public class LogInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);

    @Pointcut("@annotation(org.example.common.configs.log.LogAdvice)")
    public void logPointcut() {
        // pointcut declaration
    }

    @Before("logPointcut()")
    public void validate(JoinPoint joinPoint) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (!(requestAttributes instanceof ServletRequestAttributes)) {
            return;
        }

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Object[] args = joinPoint.getArgs();
        List<Object> list = CollectionUtil.isEmpty(Arrays.asList(args)) ? Collections.emptyList() : Arrays.asList(args);
        List<Object> logArgs =
                list.parallelStream().filter(e -> !(e instanceof ServletRequest) && !(e instanceof ServletResponse)).collect(Collectors.toList());
        LOGGER.info("---> method:[{}], url:[{}], method:[{}], parameters:[{}]", request.getMethod(), request.getRequestURL(), joinPoint.getSignature(), logArgs);

    }

    @AfterReturning(returning = "obj", pointcut = "logPointcut()")
    public void methodAfterReturning(Object obj) {
        LOGGER.info("---> response:[{}]", obj );
    }
}
